package br.com.fbv.distribuidos.model.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

/**
 * Class with useful methods to file manipulation.
 * @author Bruno Cartaxo - 2008
 */
public class FileUtil {

	public static final String FILE_SEPARATOR = File.separator;

	/**
	 * Read the content of the given file.
	 * @param path The absolute path to file.
	 * @return A String with the file content.
	 * @throws IOException
	 */
	public static String readFile(String path) throws IOException {
		StringBuffer toReturn = new StringBuffer();
		BufferedReader in = null;
		try {
			in = new BufferedReader(new FileReader(path));
			while (true) {
				String s = in.readLine();
				if (s == null) {
					break;
				}
				toReturn.append(s);
			}
		} finally {
			if (in != null) {
				in.close();
			}
		}
		return toReturn.toString();
	}

	/**
	 * Save the content to a file.
	 * @param content The file content.
	 * @param path Path to save the file.
	 * @param fileName The file name.
	 * @throws IOException
	 */
	public static void saveToFile(String content, String path, String fileName) throws IOException {
		if (!exists(path)) {
			mkdir(path);
		}
		if (!path.endsWith(File.separator)) {
			path += "/"; //$NON-NLS-1$
		}
		OutputStream out = new FileOutputStream(path + fileName);
		out.write(content.getBytes());
		out.close();
	}

	/**
	 * Save the content to file.
	 * @param content The file content
	 * @param fileName The file name
	 * @throws IOException
	 */
	public static void saveToFile(String content, String fileName) throws IOException {
		saveToFile(content, extractFilePath(fileName), extractFileName(fileName));
	}

	/**
	 * Returns the name of file.
	 * @param fileName The file name
	 * @return the name of file
	 */
	public static String extractFileName(String fileName) {
		File file = new File(fileName);
		return file.getName();
	}

	/**
	 * Returns the absolute path of file ends with separator.
	 * @param fileName The file name
	 * @return the absolute path of file ends with separator
	 */
	public static String extractFilePath(String fileName) {
		File file = new File(fileName);
		String toReturn = file.getParentFile().getAbsolutePath();
		return toReturn.endsWith(File.separator)?toReturn:toReturn + File.separator;
	}

	/**
	 * Returns if file exists in file system.
	 * @param file The file
	 * @return <code>true</code> if file exists, <code>false</code> otherwise
	 */
	public static boolean exists(String file) {
		return new File(file).exists();
	}

	/**
	 * This method creates the especified directory.
	 * @param directory The directory to create.
	 * @throws IOException
	 */
	public static void mkdir(String directory) throws IOException {
		File f = new File(directory);
		if (f.exists()) {
			if (f.isFile()) {
				throw new IOException("Unable to create directory. File " + directory + //$NON-NLS-1$
						" exists and is not a directory."); //$NON-NLS-1$
			}
		} else {
			if (!f.mkdirs()) {
				throw new IOException("Unable to create directory " + directory); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Delete the specified file, recursively as necessary.
	 * @param fileName The file to delete
	 */
	public static void delete(String fileName) {
		delete(new File(fileName));
	}

	/**
	 * Delete the specified file, recursively as necessary.
	 * @param file The file to delete
	 */
	public static void delete(File file) {
		if (file.exists()) {
			if (file.isDirectory()) {
				File[] files = file.listFiles();
				for (int i = 0; i < files.length; i++) {
					delete(files[i]);
				}
			}
			file.delete();
		}
	}

	/**
	 * This method verifies if a given file has the read and write permissions granted.
	 * @param fileName The file
	 * @return <code>true</code> if permissions are granted, <code>false</code> otherwise.
	 */
	public static boolean canReadWrite(String fileName) {
		File file = new File(fileName);
		return file.canRead() && file.canWrite();
	}

	/**
	 * This method verifies if a given file has the read permission granted.
	 * @param fileName The file
	 * @return <code>true</code> if permission is granted, <code>false</code> otherwise.
	 */
	public static boolean canRead(String fileName) {
		File file = new File(fileName);
		return file.canRead();
	}

	/**
	 * This method returns the size of a given file.
	 * @param fileName The file
	 * @return The size of a given file.
	 */
	public static Long fileSize(String fileName) {
		return new Long(new File(fileName).length());
	}

	/**
	 * This method normalize a directory path.
	 * @param folder Full path to a directory
	 * @return The normalized path.
	 */
	public static String normalizePath(String folder) {
		return folder.endsWith(File.separator)?folder:folder + File.separator;
	}

	/**
	 * This method write the given content into the given file.
	 * @param The content that will be writed.
	 * @param The path of the file that will be writed.
	 */
	public static void writeIntoFile(String fileContent, String filePath)
			throws IOException {

		Writer writer = null;

		try {
			writer = new OutputStreamWriter(new FileOutputStream(filePath, true),
					"UTF-8");
			writer.write(fileContent);
		} finally {
			if (writer != null) {
				writer.close();
			}
		}
	}

}